#define DEBUG
#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long ll;

const int maxn=100000;

class SegmentTree {
    public:
        int l, r;
        ll v;
        SegmentTree *left, *right;

        SegmentTree(int _l, int _r) {
            l=_l, r=_r;
            v=0, left=right=nullptr;
        }

        SegmentTree* create(SegmentTree *&t, int l, int r) {
            return t ? t : t = new SegmentTree(l, r);
        }

        void add(int t, ll tv) {
            if (l==r) {
                v+=tv;
            } else {
                int mid=(l+r)/2;
                SegmentTree *tar = t<=mid ? create(left, l, mid) : create(right, mid+1, r);
                tar->add(t, tv);
                v = (left ? left->v : 0) + (right ? right->v : 0);
            }
        }

        ll get(int tl, int tr) {
            if (tl>tr) {
                return 0;
            }
            tl = max(l, tl), tr = min(r, tr);
            if (l==tl && r==tr) {
                return v;
            } else {
                int mid=(l+r)/2;
                ll ret=0;
                if (tl<=mid && left) {
                    ret += left->get(tl, min(tr, mid));
                }
                if (tr>mid && right) {
                    ret += right->get(max(tl, mid+1), tr);
                }
                return ret;
            }
        }
};

class Graph {
    public:
        int n, m=1, ind[maxn+1], to[2*maxn+2], link[2*maxn+2], cir[maxn+1], dep[maxn+1], incir[maxn+1], son[maxn+1], depen[maxn+1];
        SegmentTree *f[maxn+1];
        bool vis[maxn+1];

        void addSide(int u, int v) {
            m++;
            to[m] = v;
            link[m] = ind[u];
            ind[u] = m;
        }

        bool findCir(int o) {
            static bool vis[maxn+1], used[2*maxn+1];
            static int way[maxn+1];
            vis[o] = true;
            way[++way[0]] = o;
            for (int i=ind[o]; i; i=link[i]) {
                if (!used[i]) {
                    if (vis[to[i]]) {
                        for (; way[way[0]]!=to[i]; way[0]--) {
                            cir[++cir[0]] = way[way[0]];
                            incir[way[way[0]]] = cir[0];
                        }
                        cir[++cir[0]] = way[way[0]];
                        incir[way[way[0]]] = cir[0];
                        return true;
                    } else {
                        used[i] = used[i^1] = true;
                        if (findCir(to[i])) {
                            return true;
                        }
                    }
                }
            }
            way[0]--;
            return false;
        }

        bool check(int o, int fa, int t) {
            return t!=fa && !vis[t] && (!incir[o] || !incir[t]);
        }

        int build(int o, int fa) {
            depen[o]=dep[o]=dep[fa]+1;
            for (int i=ind[o]; i; i=link[i]) {
                if (check(o, fa, to[i])) {
                    int t=build(to[i], o);
                    if (t>depen[o]) {
                        depen[o] = t;
                        son[o] = to[i];
                    }
                }
            }
            return depen[o];
        }

        ll count(int o, int fa, int k) {
            ll ret=0;
            for (int i=ind[o]; i; i=link[i]) {
                if (check(o, fa, to[i])) {
                    ret += count(to[i], o, k);
                }
            }
            if (son[o]) {
                f[o] = f[son[o]];
                for (int i=ind[o]; i; i=link[i]) {
                    int x=to[i];
                    if (check(o, fa, x) && x!=son[o]) {
                        for (int j=dep[x]; j<=depen[x]; j++) {
                            ll v=f[x]->get(j, j);
                            ret += v*f[o]->get(2*dep[o]+k-j-1, depen[o]);
                        }
                        for (int j=dep[x]; j<=depen[x]; j++) {
                            ll v=f[x]->get(j, j);
                            f[o]->add(j, v);
                        }
                    }
                }
            } else {
                f[o] = new SegmentTree(1, n);
            }
            f[o]->add(dep[o], 1);
            ret += f[o]->get(dep[o]+k-1, depen[o]);
            return ret;
        }

        ll countCir(int k) {
            if (!cir[0]) {
                build(1, 0);
                return count(1, 0, k);
            }
            static int a[2*maxn+1];
            SegmentTree *g = new SegmentTree(1, 4*n);
            ll ret=0, deb=0;
            for (int i=1; i<=cir[0]; i++) {
                a[i] = a[cir[0]+i] = cir[i];
                build(a[i], 0);
                ll t = count(a[i], 0, k);
                ret += t, deb += t;
            }
            for (int i=1; i<=2*cir[0]; i++) {
                if (i>cir[0]) {
                    for (int j=1; j<=depen[a[i]]; j++) {
                        g->add(2*n+j-(i-cir[0]), -f[a[i]]->get(j, j));
                    }
                }
                for (int j=1; j<=depen[a[i]]; j++) {
                    ret += g->get(2*n+k-i-j+1, 4*n)*f[a[i]]->get(j, j);
                }
                if (i<=cir[0]) {
                    for (int j=1; j<=depen[a[i]]; j++) {
                        g->add(2*n+j-i, f[a[i]]->get(j, j));
                    }
                }
            }
            return ret;
        }
};

int main() {
#ifdef DEBUG
    freopen("src.in", "r", stdin);
    freopen("src.out", "w", stdout);
#endif

    static Graph g;
    int n, m, k;
    scanf("%d %d %d", &n, &m, &k);
    g.n = n;
    for (int i=1; i<=m; i++) {
        int x, y;
        scanf("%d %d", &x, &y);
        g.addSide(x, y);
        g.addSide(y, x);
    }
    g.findCir(1);

    printf("%lld\n", g.countCir(k));

    fclose(stdin);
    fclose(stdout);
    return 0;
}
